
package com.bryanprogramming.zend.gui.drawables;

import java.awt.Color;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.font.LineMetrics;
import java.awt.geom.RoundRectangle2D;

/**
 *
 * @author charles bryan
 */
public class ClickableTile implements Drawable {

    private RoundRectangle2D myRectangle;
    private final int TILE_SIZE;
    private int UPDATE_SIZE;

    private char value;

    private boolean clickable = false;
    private boolean mouseOver = false;
    private boolean animating = false;
    private boolean pressed = false;
    private boolean clicked = false;
    private Color fillColor;

    public ClickableTile(RoundRectangle2D.Double info) {
        myRectangle = info;
        clickable = false;
        TILE_SIZE = (int) info.width;
        UPDATE_SIZE = TILE_SIZE / 10;
    }

    public ClickableTile(double x, double y, double w, double h, double arcw, double arch) {
        myRectangle = new RoundRectangle2D.Double(x, y, w, h, arcw, arch);
        clickable = false;
        TILE_SIZE = (int) w;
        UPDATE_SIZE = TILE_SIZE / 10;
    }

    public void reset() {
        clickable = false;
        mouseOver = false;
        animating = false;
        pressed = false;
        clicked = false;
    }

    @Override
    public void draw(Graphics g) {

        Graphics2D g2d = (Graphics2D) g;

        FontMetrics fm = g.getFontMetrics();

        int textX = (int) myRectangle.getX()
                + (int) (myRectangle.getWidth() / 2.0) - (fm.charWidth(value) / 2);

        int textY = (int) myRectangle.getY()
                + ((int) (myRectangle.getHeight() - fm.getHeight()) / 2) + fm.getAscent();

        if (animating) {
            g.setColor(Color.LIGHT_GRAY);
            g.fillRoundRect((int) myRectangle.getX() + 2, (int) myRectangle.getY() + 2, (int) myRectangle.getWidth(), (int) myRectangle.getHeight(), (int) myRectangle.getArcWidth(), (int) myRectangle.getArcHeight());

            g.setColor(getColor(value));

            int offSetX = (int) myRectangle.getX() + (TILE_SIZE / 2) - (UPDATE_SIZE) / 2;
            int offSetY = (int) myRectangle.getY() + (TILE_SIZE / 2) - (UPDATE_SIZE) / 2;
            g.fillRoundRect(offSetX, offSetY, UPDATE_SIZE, UPDATE_SIZE, UPDATE_SIZE / (int) myRectangle.getArcWidth(), UPDATE_SIZE / (int) myRectangle.getArcHeight());
            UPDATE_SIZE += 5;
            if (UPDATE_SIZE >= TILE_SIZE) {
                animating = false;
                UPDATE_SIZE = 8;
            }

        }
        else if (clickable && clicked) {
            g.setColor(Color.GRAY);
            g.fillRoundRect((int) myRectangle.getX() + 2, (int) myRectangle.getY() + 2, (int) myRectangle.getWidth(), (int) myRectangle.getHeight(), (int) myRectangle.getArcWidth(), (int) myRectangle.getArcHeight());
            g.setColor(getContrastColor(this.fillColor));
            g2d.fill(myRectangle);

            g.setColor(getColor(value));
            g.fillRoundRect((int) myRectangle.getX() + 3, (int) myRectangle.getY() + 3, (int) myRectangle.getWidth() - 6, (int) myRectangle.getHeight() - 6, (int) myRectangle.getArcWidth(), (int) myRectangle.getArcHeight());
            g.setColor(getContrastColor(this.fillColor));
            g.drawString(String.valueOf(value), textX, textY);
        }
        else if (clickable && mouseOver) {
            g.setColor(Color.GRAY);
            g.fillRoundRect((int) myRectangle.getX() + 2, (int) myRectangle.getY() + 2, (int) myRectangle.getWidth(), (int) myRectangle.getHeight(), (int) myRectangle.getArcWidth(), (int) myRectangle.getArcHeight());

            g.setColor(getColor(value));
            if (pressed) {
                g.fillRoundRect((int) myRectangle.getX() + 1, (int) myRectangle.getY() + 1, (int) myRectangle.getWidth(), (int) myRectangle.getHeight(), (int) myRectangle.getArcWidth(), (int) myRectangle.getArcHeight());
                g.setColor(getContrastColor(this.fillColor));
                g.drawString(String.valueOf(value), textX + 1, textY + 1);
            }
            else {

                g2d.fill(myRectangle);
                g.setColor(getContrastColor(this.fillColor));
                g.drawString(String.valueOf(value), textX, textY);
            }
        }
        else {

            g.setColor(Color.LIGHT_GRAY);
            g.fillRoundRect((int) myRectangle.getX() + 2, (int) myRectangle.getY() + 2, (int) myRectangle.getWidth(), (int) myRectangle.getHeight(), (int) myRectangle.getArcWidth(), (int) myRectangle.getArcHeight());

            g.setColor(getColor(value));
            g2d.fill(myRectangle);
            g.setColor(getContrastColor(this.fillColor));
            g.drawString(String.valueOf(value), textX, textY);
        }
    }

    /**
     * @param value the value to set
     */
    public void setValue(char value) {
        this.value = value;
        this.fillColor = getColor(value);
    }

    public void animateGrow() {
        this.animating = true;
    }

    public void setClickable(boolean isClickable) {
        this.clickable = isClickable;
    }

    public void setMouseOver(boolean isMouseOver) {
        this.mouseOver = isMouseOver;
    }

    public void setPressed(boolean isPressed) {
        this.pressed = isPressed;
    }

    public void setClicked(boolean isClicked) {
        this.clicked = isClicked;
    }

    /**
     * Returns true when the Point object is found inside this ClickableTile object. 
     * @param mouse
     * @return 
     */
    public boolean isMouseOver(Point mouse) {
        return this.myRectangle.contains(mouse.x, mouse.y);
    }

    /**
     * Spreads the color spectrum over the 26 capital letters in the English alphabet and returns
     * the equivalent Color object for the parameter capitalLetter. Will take any character and % 26
     * based on that value so any char value WILL return a color but that color is not guaranteed. 
     * 
     * @param capitalLetter The Capital letter 
     * @return The associated Color object with capitalLetter
     */
    private Color getColor(char capitalLetter) {
        float percent = ((capitalLetter - 65) % 26) / 26.0f;

        float r = 0.0f, g = 0.0f, b = 0.0f;

        if (0f <= percent && percent <= .125f) {
            b = 4.0f * percent + .5f;
        }
        else if (0.125f < percent && percent <= .375f) {
            g = 4.0f * percent - .5f;
            b = 1.0f;
        }
        else if (0.375f < percent && percent <= .625f) {
            r = 4.0f * percent - 1.5f;
            g = 1.0f;
            b = -4.0f * percent + 2.5f;
        }
        else if (0.625f < percent && percent <= .875f) {
            r = 1.0f;
            g = -4.0f * percent + 3.5f;
        }
        else if (0.875f < percent && percent <= 1.0f) {
            r = -4.0f * percent + 4.5f;
        }
        else {
            r = g = b = 1.0f;
        }
        return new Color(r, g, b);
    }

    /**
     * Returns Color.WHITE or Color.BLACK based on the contrast of the parameter Color color.
     * Dark colors will return Color.WHITE while light colors will return Color.BLACK.
     * @param color The Color that the contrast is being determined. 
     * @return Color.WHITE or Color.BLACK based on the contrast of color.
     */
    private Color getContrastColor(Color color) {
        double a = 1 - (0.299 * color.getRed() + 0.587 * color.getGreen() + 0.114 * color.getBlue()) / 255;

        if (a < 0.5) {
            return Color.BLACK;
        }
        else {
            return Color.WHITE;
        }
    }

}
